﻿using System.Collections.Generic;
using System.Threading.Tasks;

namespace Sidvall.Logging
{
    public class LogManager
    {
        #region Public Members

        public bool IgnoreLogErrors { get; set; }
        public Sidvall.Logging.ILog Log { get; set; }
        #region ExceptionManager

        private Sidvall.ExceptionHandling.ExceptionManager _ExceptionManager;
        public Sidvall.ExceptionHandling.ExceptionManager ExceptionManager
        {
            get
            {
                if (_ExceptionManager != null)
                    return _ExceptionManager;
                return Sidvall.SystemContext.Current.SystemExceptionManager;
            }
            set
            {
                _ExceptionManager = value;
            }
        }

        #endregion

        #region ShouldLog

        public bool ShouldLog(IEnumerable<string> categories, EventType severity)
        {
            if (this.Log != null)
                return this.Log.ShouldLog(categories, severity);
            return false;
        }

        #endregion
        #region WriteAsync

        public async Task WriteAsync(System.Exception ex)
        {
            await WriteAsync(ex, string.Empty).ConfigureAwait(false);
        }
        public async Task WriteAsync(System.Exception ex, string category)
        {
            await WriteAsync(ex, GetCategories(category)).ConfigureAwait(false);
        }
        public async Task WriteAsync(System.Exception ex, IEnumerable<string> categories)
        {
            if (ex == null)
                return;
            await WriteAsync(ex.Message, this.ExceptionManager.GetMessage(ex), categories, EventType.Error).ConfigureAwait(false);
        }
        public async Task WriteAsync(System.Exception ex, IEnumerable<string> categories, IDictionary<string, string> properties)
        {
            if (ex == null)
                return;
            await WriteAsync(ex.Message, this.ExceptionManager.GetMessage(ex), categories, EventType.Error, properties).ConfigureAwait(false);
        }

        public async Task WriteAsync(IEnumerable<System.Exception> exceptions)
        {
            await WriteAsync(exceptions, string.Empty).ConfigureAwait(false);
        }
        public async Task WriteAsync(IEnumerable<System.Exception> exceptions, string category)
        {
            if (exceptions == null)
                return;
            foreach (var ex in exceptions)
                await WriteAsync(ex, category).ConfigureAwait(false);
        }

        public async Task WriteAsync(string title, string message)
        {
            await WriteAsync(title, message, string.Empty).ConfigureAwait(false);
        }
        public async Task WriteAsync(string title, string message, string category)
        {
            await WriteAsync(title, message, category, EventType.Information).ConfigureAwait(false);
        }
        public async Task WriteAsync(string title, string message, string category, EventType severity)
        {
            await WriteAsync(title, message, GetCategories(category), severity).ConfigureAwait(false);
        }
        public async Task WriteAsync(string title, string message, IEnumerable<string> categories, EventType severity)
        {
            await WriteAsync(title, message, categories, severity, null).ConfigureAwait(false);
        }
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")]
        public async Task WriteAsync(string title, string message, IEnumerable<string> categories, EventType severity, IDictionary<string, string> properties)
        {
            if (this.Log != null)
            {
                if (this.IgnoreLogErrors)
                {
                    try
                    {
                        await this.Log.WriteAsync(title, message, categories, severity, properties).ConfigureAwait(false);
                    }
                    catch
                    {
                    }
                }
                else
                {
                    await this.Log.WriteAsync(title, message, categories, severity, properties).ConfigureAwait(false);
                }
            }
        }

        #endregion
        #region ToString

        public override string ToString()
        {
            return "LogManager - Sidvall.Logging.ILog";
        }

        #endregion

        #endregion
        #region Private Members

        #region GetCategories

        private static List<string> GetCategories(string category)
        {
            if (!string.IsNullOrWhiteSpace(category))
            {
                var items = new List<string>();
                items.Add(category);
                return items;
            }
            else
                return null;
        }

        #endregion

        #endregion
        #region Constructors

        public LogManager(Sidvall.Logging.ILog log)
        {
            this.IgnoreLogErrors = true;
            this.Log = log;
        }

        #endregion
    }
}
